using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
using System.Collections.Generic;

namespace Dida
{
	public class PlayerPawn : Pawn, IStateMachineUser<PlayerControllerGlue>
	{
		IStateMachine<PlayerControllerGlue> controller;

		public PlayerPawn(float radius, float height, int nSpheres,
			IStateMachine<PlayerControllerGlue> controller)
			: base(GetStackedSpheres(radius,height,nSpheres))
		{
			this.controller = controller;
		}

		public override void Start()
		{
			controller.Start(this);
			base.Start();
		}

		public override void Stop()
		{
			controller.Stop();
			base.Stop();
		}

		public override void Update(float timeDelta)
		{
			controller.GetCurStateGlue().Update(timeDelta, World.viewpoint);
			base.Update(timeDelta);
		}

		void IStateMachineUser<PlayerControllerGlue>.InitializeGlue(PlayerControllerGlue glue)
		{
			glue.SetPawn(this);
		}
	}

	public abstract class PlayerControllerGlue : StateGlueTrait
	{
		Pawn pawn;

		internal void SetPawn(Pawn pawn)
		{
			this.pawn = pawn;
		}

		[TraitImplementMethod(NeedsDeclaration=false)]
		public Pawn GetPawn()
		{
			Debug.Assert(pawn != null, "The pawn hasn't been set for this state");
			return pawn;
		}

		[TraitDeclareMethod(TraitMethodAcceptance.MultipleImplementations)]
		public virtual void Update(float timeDelta, Viewpoint viewpt) { }
	}

	public abstract class StateController : StateTrait<PlayerControllerGlue>
	{
		[TraitImplementMethod]
		public virtual void OnActivated(StateActivatedReason reason) { }
		[TraitImplementMethod]
		public virtual void OnDeactivated(StateDeactivatedReason reason) { }
		[TraitImplementMethod]
		public abstract void Update(float timeDelta,Viewpoint viewpt);

		[TraitDeclareMethod(TraitMethodAcceptance.SingleImplementation)]
		public abstract Pawn GetPawn();

		public Pawn Pawn
		{
			get { return GetPawn(); }
		}
	}

	public abstract class PlayerStateTransition : StateTransition<PlayerControllerGlue>
	{
	}
}